<template>
    <div>
        <!-- 搜索 & 按钮 -->
        <el-form class="search" inline label-width="80px">
            <el-form-item v-for="col in c.searchCols" :key="col.prop">
                <el-select v-if="col.type == 'select'" :placeholder="col.label" v-model="search[col.prop]" clearable="">
                    <el-option v-for="v in dict[col.prop]" :key="v.value" :label="v.label" :value="v.value" />
                </el-select>
                <template v-else-if="$scopedSlots['search-'+col.prop]">
                    <slot :name="'search-'+col.prop" :search="search" />
                </template>
                <el-input v-else :placeholder="col.label" v-model="search[col.prop]" />
            </el-form-item>
            <el-form-item>
                <el-button v-if="c.isSearchBtn" size="mini" type="primary" @click="searchHandler()">搜索</el-button>
                <el-button v-if="c.isSearchBtn" size="mini" type="danger" @click="resetHandler()">重置</el-button>
                <el-button size="mini" type="primary" @click="addHandler">新增</el-button>
                <el-button size="mini" type="warning" @click="exportHandler">导出</el-button>
            </el-form-item>
        </el-form>
        <!-- 表格 -->
        <el-table size="medium" :data="tableData" v-loading="tableLoad">
            <el-table-column v-for="col in c.tableCols" :key="col.prop + col.label" :label="col.label">
                <template v-slot="{ row }">
                    <div v-if="col.type == 'select'">
                        {{tableColsDictFilter(row[col.prop], dict[col.prop])}}
                    </div>
                    <div v-else-if="$scopedSlots['table-'+col.prop]">
                        <slot :name="'table-'+col.prop" :row="row" />
                    </div>
                    <div v-else>
                        {{row[col.prop]}}
                    </div>
                </template>
            </el-table-column>
            <el-table-column width="160px" align="center" label="操作">
                <template v-slot="{ row }">
                    <div>
                        <el-button size="mini" type="primary" @click="editHandler(row)">编辑</el-button>
                        <el-button size="mini" type="danger" @click="delHandler(row)">删除</el-button>
                    </div>
                </template>
            </el-table-column>
        </el-table>
        <!-- 分页 -->
        <el-pagination v-if="c.isPage" style="text-align: right; padding: 15px 0;" background layout="total, sizes, prev, pager, next, jumper" :total="page.total" @size-change="sizeChange" @current-change="currentChange" />
        <!-- 弹窗 -->
        <el-dialog class="dialog" :visible.sync="dialog.show" :width="c.dialogWidth" :title="dialog.title">
            <el-form inline :label-width="c.dialogLabelWidth">
                <template v-for="col in c.dialogCols">
                    <el-form-item v-if="$scopedSlots['dialog-'+col.prop]" :key="col.prop" :label="col.label">
                        <slot :name="'dialog-'+col.prop" :form="dialog.form" />
                    </el-form-item>
                    <el-form-item v-else-if="col.type == 'select'" :key="col.prop" :label="col.label">
                        <el-select v-model="dialog.form[col.prop]" :placeholder="'请选择'+col.label" clearable>
                            <el-option v-for="v in dict[col.prop]" :key="v.value" :label="v.label" :value="v.value" />
                        </el-select>
                    </el-form-item>
                    <el-form-item v-else-if="col.type == 'radio'" :key="col.prop" :label="col.label" style="display: block;">
                        <el-radio-group v-model="dialog.form[col.prop]">
                            <el-radio v-for="v in dict[col.prop]" :key="v.value" :label="v.value">{{v.label}}</el-radio>
                        </el-radio-group>
                    </el-form-item>
                    <el-form-item v-else-if="col.type == 'textarea'" :key="col.prop" :label="col.label" class="dialog-textarea">
                        <el-input v-model="dialog.form[col.prop]" :placeholder="'请填写'+col.label" clearable type="textarea" rows="3" />
                    </el-form-item>
                    <el-form-item v-else :key="col.prop" :label="col.label">
                        <el-input v-model="dialog.form[col.prop]" :placeholder="'请填写'+col.label" clearable />
                    </el-form-item>
                </template>
            </el-form>
            <template v-slot:footer>
                <el-button size="mini" type="text" @click="dialog.show = false">取消</el-button>
                <el-button size="mini" type="primary" @click="submitHandler">确定</el-button>
            </template>
        </el-dialog>
    </div>
</template>

<script>
/*
    自定义事件：
    refreshAfter：获取数据后
    submitClick：提交点击
*/
import { xlsExport } from '@/utils'
export default {
    props: {
        // CRUD全局配置
        config: {
            type: Object,
            default: _ => { }
        },
        // 接口集合
        apis: {
            type: Object,
            default: _ => { }
        },
        // 字典
        dict: {
            type: Object,
            default: _ => { }
        }
    },
    computed: {
        // 配置
        c() {
            let {
                // 表格列
                tableCols = [],
                // 搜索项
                searchCols = [],
                // 弹窗项
                dialogCols = [],
                // 弹窗-宽度
                dialogWidth = '620px',
                // 弹窗-表单项-宽度
                dialogLabelWidth = '80px',
                // 是否需要搜索（重置）按钮
                isSearchBtn = Boolean(this.config.searchCols && this.config.searchCols.length),
                // 是否需要分页组件
                isPage = true
            } = this.config
            return {
                tableCols,
                searchCols,
                dialogCols,
                dialogWidth,
                dialogLabelWidth,
                isSearchBtn,
                isPage
            }
        },
        // 表格下拉过滤
        tableColsDictFilter() {
            return function (v, dict) {
                if (!dict || !dict.length) return ''
                for (let i = 0; i < dict.length; i++) {
                    if (dict[i].value == v) {
                        return dict[i].label
                    }
                }
            }
        }
    },
    data() {
        return {
            // 搜索
            search: {},
            // 分页
            page: {},
            // 表格数据
            tableData: [],
            // 表格loading
            tableLoad: false,
            // 弹窗
            dialog: {
                show: false,
                title: '',
                form: {}
            }
        }
    },
    created() {
        this.resetHandler()
    },
    methods: {
        // 搜索-重置
        resetHandler() {
            this.resetPage()
            this.search = {}
            this.getPage()
        },
        // 搜索
        searchHandler() {
            this.resetPage()
            this.getPage()
        },
        // 分页-重置
        resetPage() {
            this.page = {
                pageNum: 1,
                pageSize: 10,
                total: 0
            }
        },
        // 分页-分页大小改变
        sizeChange(e) {
            this.page.pageSize = e
            this.getPage()
        },
        // 分页-当前页改变
        currentChange(e) {
            this.page.pageNum = e
            this.getPage()
        },
        // 获取列表
        async getPage() {
            this.tableLoad = true
            let p = Object.assign({}, this.page, this.search)
            let res = await this.apis.refresh(p)
            this.$listeners.refreshAfter && this.$listeners.refreshAfter(res)
            this.tableData = res.data.rows
            this.page.total = res.data.total
            this.tableLoad = false
        },
        // 新增
        addHandler() {
            this.dialog = {
                show: true,
                title: '新增',
                form: {}
            }
        },
        // 编辑
        editHandler(row) {
            this.dialog = {
                show: true,
                title: '编辑',
                form: JSON.parse(JSON.stringify(row))
            }
        },
        // 确认-提交
        async submitHandler() {
            let callback = async form => {
                form = form ? form : this.dialog.form
                this.dialog.title.match('编辑') ? await this.apis.update(form) : await this.apis.add(form)
                this.dialog.show = false
                this.getPage()
            }
            this.$listeners.submitClick ? this.$listeners.submitClick(this.dialog.form, callback) : callback()
        },
        // 删除
        async delHandler(row) {
            await this.apis.del(row)
            this.getPage()
        },
        // 导出
        exportHandler() {
            let obj = {
                header: this.c.tableCols.map(item => item.label),
                props: this.c.tableCols.map(item => item.prop),
                sourceData: this.tableData,
                fileName: this.$route.meta.title
            }
            let callback = res => {
                res = res ? res : obj
                xlsExport(res)
            }
            this.$listeners.exportClick ? this.$listeners.exportClick(obj, callback) : callback()
        }
    }
}
</script>

<style lang="scss" scoped>
// 搜索区域样式
.search {
    flex-wrap: wrap;
    justify-content: space-between;
    ::v-deep .el-form-item {
        margin-bottom: 5px;
    }
    // 控件宽度控制在200
    ::v-deep .el-input {
        width: 200px;
    }
}
// 弹窗区域样式
.dialog {
    // 控件宽度控制在200
    ::v-deep .el-input {
        width: 200px;
    }
    // 文本域
    .dialog-textarea {
        display: flex;
        width: 100%;
        ::v-deep .el-form-item__content {
            flex: 1;
            margin-right: 10px;
        }
    }
}
</style>